/*
Copyright (c) 2010 Andi Rustandi Djunaedi andird@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
 */
package com.appspot.mobileirisnextbus.client;

import java.util.List;

import com.appspot.mobileirisnextbus.shared.Constants;
import com.appspot.mobileirisnextbus.shared.Util;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class MobileIrisNextBus implements EntryPoint {
	/**
	 * Create a remote service proxy to talk to the server-side Greeting
	 * service.
	 */
	private final BusServiceAsync busService = GWT.create(BusService.class);

	/**
	 * This is the entry point method.
	 */
	@Override
	public void onModuleLoad() {
		final Label serverResponseLabel = new Label();
		final HorizontalPanel inputPanel = new HorizontalPanel();
		final Label busStopLabel = new Label("Bus Stop");
		final TextBox busStopField = new TextBox();
		final Button sendButton = new Button("Submit");
		final FlexTable resultTable = new FlexTable();

		// everthing will be put in main panel
		final VerticalPanel mainPanel = new VerticalPanel();
		mainPanel.add(serverResponseLabel);
		mainPanel.add(inputPanel);
		mainPanel.add(sendButton);
		mainPanel.add(resultTable);

		// add to root panel
		RootPanel.get("container").add(mainPanel);

		// setup input panel
		inputPanel.add(busStopLabel);
		inputPanel.add(busStopField);

		// Focus the cursor on the name field when the app loads
		busStopField.setFocus(true);
		busStopField.selectAll();

		// Create a handler for the sendButton and nameField
		class InputHandler implements ClickHandler, KeyUpHandler, ChangeHandler {
			@Override
			public void onChange(final ChangeEvent event) {
				this.sendNameToServer();
			}

			/**
			 * Fired when the user clicks on the sendButton.
			 */
			@Override
			public void onClick(final ClickEvent event) {
				this.sendNameToServer();
				// Focus the cursor on the name field after submit
				busStopField.setFocus(true);
				busStopField.selectAll();
			}

			/**
			 * Fired when the user types in the nameField.
			 */
			@Override
			public void onKeyUp(final KeyUpEvent event) {
				if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
					this.sendNameToServer();
				}
			}

			/**
			 * Send the name from the nameField to the server and wait for a
			 * response.
			 */
			private void sendNameToServer() {
				// First, we validate the input.
				final String textToServer = busStopField.getText();
				if (!Util.isNumber(textToServer)) {
					// if not number, do nothing
					return;
				}

				// Then, we send the input to the server.
				sendButton.setEnabled(false);
				serverResponseLabel.setText("");
				MobileIrisNextBus.this.busService.getBuses(textToServer,
						new AsyncCallback<List<String>>() {
							@Override
							public void onFailure(final Throwable caught) {
								// Show the RPC error message to the user
								serverResponseLabel
										.addStyleName("serverResponseLabelError");
								serverResponseLabel
										.setText(Constants.SERVER_ERROR);
							}

							@Override
							public void onSuccess(final List<String> svcList) {
								serverResponseLabel
										.removeStyleName("serverResponseLabelError");
								resultTable.setText(0, 0, "Bus");
								resultTable.setText(0, 1, "Next");
								resultTable.setText(0, 2, "Subsequent");
								int svcRowIdx = 1;
								for (final String svc : svcList) {
									resultTable.setText(svcRowIdx, 0, svc);
									resultTable.setText(svcRowIdx, 1, "...");
									resultTable.setText(svcRowIdx, 2, "...");
									final int currSvcRowIdx = svcRowIdx;
									MobileIrisNextBus.this.busService
											.getBusTime(
													textToServer,
													svc,
													new AsyncCallback<List<String>>() {
														@Override
														public void onFailure(
																final Throwable caught) {
															resultTable
																	.setText(
																			currSvcRowIdx,
																			1,
																			"NA");
															resultTable
																	.setText(
																			currSvcRowIdx,
																			2,
																			"NA");
														}

														@Override
														public void onSuccess(
																final List<String> times) {
															int idxCol = 0;
															for (final String time : times) {
																resultTable
																		.setText(
																				currSvcRowIdx,
																				idxCol + 1,
																				time);
																idxCol++;
															}
														}
													});
									svcRowIdx++;
								}
								sendButton.setEnabled(true);
							}
						});
			}
		}

		// Add a handler to send the name to the server
		final InputHandler handler = new InputHandler();
		sendButton.addClickHandler(handler);
		busStopField.addChangeHandler(handler);
		busStopField.addKeyUpHandler(handler);
	}
}
